/**
 * @Project RSLsXWG
 * @Author Tran Manh Hung
 * @Email: hungtmit@gmail.com | tmh@xwebgate.com
 * @Copyright © 2011 TMH. All rights reserved
 * @Createdate May 2, 2011
 * @Createtime 10:42:49 AM
 */

package com.xwg.cards
{
	import com.xwg.cards.events.CardEvent;

	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;

	public class Card extends EventDispatcher implements IEventDispatcher
	{

		public static const ACE:String = "A"; // 1

		public static const CLUBS:String = "♣"; // 1

		public static const DIAMONDS:String = "♦"; // 2

		public static const HEARTS:String = "♥"; // 3

		public static const JACK:String = "J"; // 11

		public static const KING:String = "K"; // 13

		public static const QUEEN:String = "Q"; // 12

		public static const SPADES:String = "♠"; // 4

		/**
		 * is card interactable?<br />
		 * <b>EG:</b><br />
		 * card can be select, drag,...<br />
		 */
		private var _interactable:Boolean;

		/**
		 * is card on hand or threw<br />
		 */
		private var _onHand:Boolean;

		/**
		 * rank of card value<br />
		 * <b>EG:</b><br />
		 * in "Ba cây" order of rank is A > 9 > 8 > 7 > 6 > 5 > 4 > 3 > 2<br />
		 * in "Tiến lên" order of rank is 2 > A > K > Q > J > 10 > 9 > 8 > 7 > 6 > 5 > 4 > 3<br />
		 * in "Black Jack" rank of all values are equal<br />
		 */
		private var _rank:int;

		/**
		 * is card revealed to see it suit and value?<br />
		 */
		private var _revealed:Boolean;

		/**
		 * is card selected to do something<br />
		 * <b>EG:</b><br />
		 * throw to table<br />
		 */
		private var _selected:Boolean;

		/**
		 * spades (♠), hearts (♥), diamonds (♦), clubs (♣)<br />
		 */
		private var _suit:String;

		/**
		 * rank of suit<br />
		 * <b>EG:</b><br />
		 * in "Ba cây" order of suit rank is ♦ > ♥ > ♣ > ♠<br />
		 * in "Tiến lên" order of suit rank is ♥ > ♦ > ♣ > ♠<br />
		 * in "Poker" rank of all suits are equal<br />
		 */
		private var _suitRank:int;

		/**
		 * A(ce), 2, 3, 4, 5, 6, 7, 8, 9, 10, J(ack), Q(ueen), K(ing)<br />
		 */
		private var _value:String;

		/**
		 * is card visible on table?<br />
		 */
		private var _visible:Boolean;

		/**
		 * order in deck | from light to heavy (small to big)...<br />
		 * use for shuffle deck<br />
		 */
		private var _weight:Number;

		public function Card(value:String = '', suit:String = '', target:IEventDispatcher = null)
		{
			super(target);

			_value = value;
			_rank = 0; // same rank
			_suit = suit;
			_suitRank = 0; // same rank
			_weight = 0;
			_onHand = false;
			_selected = false;
			_visible = false;
		}

		public function resetData():void
		{
			_value = '';
			_rank = 0; // same rank
			_suit = '';
			_suitRank = 0; // same rank
			_weight = 0;
			_onHand = false;
			_selected = false;
			_visible = false;
		}

		public static function valueFromInt(value:int):String
		{
			var ret:String;

			switch (value)
			{
				case 1:
					ret = Card.ACE;
					break;
				case 2:
				case 3:
				case 4:
				case 5:
				case 6:
				case 7:
				case 8:
				case 9:
				case 10:
					ret = value.toString();
					break;
				case 11:
					ret = Card.JACK;
					break;
				case 12:
					ret = Card.QUEEN;
					break;
				case 13:
					ret = Card.KING;
					break;
				default:
					ret = "";
					break;
			}

			return ret;
		}

		public static function suitFromInt(suite:int):String
		{
			var ret:String;

			switch (suite)
			{
				case 1:
					ret += Card.CLUBS;
					break;
				case 2:
					ret += Card.DIAMONDS;
					break;
				case 3:
					ret += Card.HEARTS;
					break;
				case 4:
					ret += Card.SPADES;
					break;
				default:
					ret += "";
					break;
			}

			return ret;
		}

		/**
		 * value from 1 to 13: A 2 3 4 5 6 7 8 9 10 J Q K
		 * suit from 1 to 4: clubs diamonds hearts spades
		 */
		public function setCard(value:String = '', suit:String = ''):void
		{
			this.value = value;
			this.suit = suit;

			var e:CardEvent = new CardEvent(CardEvent.CARD_VALUE_CHANGE);
			dispatchEvent(e);
		}

		/**
		 * toggle value of _selected property
		 */
		public function toggleSelection():void
		{
			if (_selected)
			{
				selected = false;
			}
			else
			{
				selected = true;
			}
		}

		public function toStringExt(prefix:String = ""):String
		{
			var ret:String = prefix;

			switch (_value)
			{
				case Card.ACE:
					ret += "A";
					break;
				case "2":
				case "3":
				case "4":
				case "5":
				case "6":
				case "7":
				case "8":
				case "9":
				case "10":
					ret += _value.toString();
					break;
				case Card.JACK:
					ret += "J";
					break;
				case Card.QUEEN:
					ret += "Q";
					break;
				case Card.KING:
					ret += "K";
					break;
				default:
					ret += "-";
					break;
			}

			switch (_suit)
			{
				case Card.CLUBS:
					ret += "♣";
					break;
				case Card.DIAMONDS:
					ret += "♦";
					break;
				case Card.HEARTS:
					ret += "♥";
					break;
				case Card.SPADES:
					ret += "♠";
					break;
				default:
					ret += "-";
					break;
			}

			return ret;
		}

		protected function rankFromValue(value:String):void
		{
			switch (value)
			{
				case Card.ACE:
					_rank = 14;
					break;
				case "2":
					_rank = 15;
					break;
				case "3":
				case "4":
				case "5":
				case "6":
				case "7":
				case "8":
				case "9":
				case "10":
					_rank = int(value);
					break;
				case Card.JACK:
					_rank = 11;
					break;
				case Card.QUEEN:
					_rank = 12;
					break;
				case Card.KING:
					_rank = 13;
					break;
				default:
					_rank = 0;
					break;
			}
		}

		protected function rankSuitFromSuite(suit:String):void
		{
			switch (suit)
			{
				case Card.CLUBS:
					_suitRank = 2;
					break;
				case Card.DIAMONDS:
					_suitRank = 3;
					break;
				case Card.HEARTS:
					_suitRank = 4;
					break;
				case Card.SPADES:
					_suitRank = 1;
					break;
				default:
					_suitRank = 0;
					break;
			}
		}

		public function get suit():String
		{
			return _suit;
		}

		public function set suit(value:String):void
		{
			_suit = value;

			rankSuitFromSuite(_suit);
		}

		public function get value():String
		{
			return _value;
		}

		public function set value(value:String):void
		{
			_value = value;

			rankFromValue(_value);
		}

		public function get weight():Number
		{
			return _weight;
		}

		public function set weight(value:Number):void
		{
			_weight = value;
		}

		public function get rank():int
		{
			return _rank;
		}

		public function set rank(value:int):void
		{
			_rank = value;
		}

		public function get suitRank():int
		{
			return _suitRank;
		}

		public function set suitRank(value:int):void
		{
			_suitRank = value;
		}

		public function get onHand():Boolean
		{
			return _onHand;
		}

		public function set onHand(value:Boolean):void
		{
			_onHand = value;
		}

		public function get selected():Boolean
		{
			return _selected;
		}

		public function set selected(value:Boolean):void
		{
			_selected = value;
		}

		public function get revealed():Boolean
		{
			return _revealed;
		}

		public function set revealed(value:Boolean):void
		{
			_revealed = value;

			var e:CardEvent = new CardEvent(CardEvent.CARD_REVEAL_CARD_CHANGE);
			dispatchEvent(e);
		}

		public function get interactable():Boolean
		{
			return _interactable;
		}

		public function set interactable(value:Boolean):void
		{
			_interactable = value;

			var e:CardEvent = new CardEvent(CardEvent.CARD_INTERACTABLE_CHANGE);
			dispatchEvent(e);
		}

		public function get visible():Boolean
		{
			return _visible;
		}

		public function set visible(value:Boolean):void
		{
			_visible = value;

			var e:CardEvent = new CardEvent(CardEvent.CARD_VISIBLE_CHANGE);
			dispatchEvent(e);
		}
	}
}
